/*************************************************************************
	Base Class of Button, EditBox，Slider，etc 

*************************************************************************/

using UnityEngine;
using System;
using System.Collections;

[Serializable]
public class UKagControlBase_SaveData
{
	public UKagControlBase_SaveData() {}
		
	public string stateAnimNamePrefix;
	public bool isAnim = false;
	public int tabIdx = -1;
	public bool isSys = false;
		
	public bool focus = false;
	public bool disable = false;
	public bool mouseDown = false;
	
	public string enterSE = null;
	public string leaveSE = null;
	public string clickSE = null;
}

[RequireComponent(typeof(UTVPAnimationLayer))]
public abstract class UKagControlBase : MonoBehaviour, IComparable<UKagControlBase> {
	protected UKagSystem mSystem = null;
	protected UKagStorages mStorages = null;
	protected UKagMessageLayer mParent = null;
	public UKagMessageLayer parent { get { return mParent; } }

	public string stateAnimNamePrefix;
	protected bool mIsAnim = false;
	public bool isAnim { get { return mIsAnim; } }
	public int tabIdx = -1;
	protected UTVPAnimationLayer mTargetLayer = null;
	protected UTVPAnimationLayer[] mLayerObjs = null;
	protected bool mIsSys = false;
	public bool isSys { get { return mIsSys; } }
	public bool visible { get { return mTargetLayer.Visible; } set { mTargetLayer.Visible = value; } }
	
	protected bool mFocus = false;
	protected bool mDisable = false;
	protected bool mMouseDown = false;
	
	public AudioClip enterSE = null;
	public AudioClip leaveSE = null;
	public AudioClip clickSE = null;
	
	public static T CreateControl<T>(UTVPSystem system, UKagMessageLayer parent, string name, int gameObjLayer) where T : UKagControlBase
	{
		if (parent == null)
			return null;
		
		UTVPAnimationLayer controlLayer = UTVPLayer.CreateLayer<UTVPAnimationLayer>(system, parent.Frame, name, gameObjLayer);
		T control = controlLayer.gameObject.AddComponent<T>();
		control.mSystem = (UKagSystem)system;
		control.mStorages = (UKagStorages)system.Storages;
		control.mParent = parent;
		
		return control;
	}
	
	// Use this for initialization
	protected virtual void Awake () {
		mTargetLayer = GetComponent<UTVPAnimationLayer>();
		mTargetLayer.HitType = UTVPLayer.HIT_TYPE.ALWAYS;
		mTargetLayer.onMouseMoveDelegate = MouseMoveHandler;
		mTargetLayer.onMouseDownDelegate = MouseDownHandler;
		mTargetLayer.onMouseUpDelegate = MouseUpHandler;
		mTargetLayer.onMouseEnterDelegate = MouseEnterHandler;
		mTargetLayer.onMouseLeaveDelegate = MouseLeaveHandler;
		mLayerObjs = new UTVPAnimationLayer[1];
		mLayerObjs[0] = mTargetLayer;
	}
	
	protected virtual void Start() {
	}
	
	protected abstract void RefreshControlState();
	
	public UTVPAnimationLayer layer { get {return mTargetLayer; } }
	public UTVPAnimationLayer[] layerObjs { get { return mLayerObjs; } }
	
	public bool disable
	{
		get { return mDisable; }
		set
		{
			if (mDisable == value)
				return;
			
			mDisable = value;
			
			RefreshControlState();
		}
	}
	
	public bool focus
	{
		get { return mFocus; }
		set
		{
			if (mFocus == value)
				return;
			
			mFocus = value;
			if (!mFocus)
				mMouseDown = false;
			if (mFocus)
				mParent.FocusedControl = this;
			
			RefreshControlState();
		}
	}
	
	public bool mouseDown
	{
		get { return mMouseDown; }
		set
		{
			if (mMouseDown == value)
				return;
			
			mMouseDown = value;
			if (!mFocus)
				mMouseDown = false;
			
			RefreshControlState();
		}
	}
	
	private void MouseMoveHandler(UTVPLayer layer, int x, int y, float dx, float dy, int shift)
	{
		if (!disable)
			OnMouseMove_impl(layer, x, y, dx, dy, shift);
	}
	protected virtual void OnMouseMove_impl(UTVPLayer layer, int x, int y, float dx, float dy, int shift) {}
	
	private void MouseDownHandler(UTVPLayer layer, int x, int y, KeyCode button, int shift)
	{
		if (!disable)
			OnMouseDown_impl(layer, x, y, button, shift);
	}
	protected virtual void OnMouseDown_impl(UTVPLayer layer, int x, int y, KeyCode button, int shift)
	{
		if (!mMouseDown)
		{
			mouseDown = true;
		
			if (clickSE != null)
				mSystem.SystemSeBuf.play(clickSE);
			else if (mSystem.DefaultCtlClickSE != null)
				mSystem.SystemSeBuf.play(mSystem.DefaultCtlClickSE);
		}
	}
	
	private void MouseUpHandler(UTVPLayer layer, int x, int y, KeyCode button, int shift)
	{
		if (!disable)
			OnMouseUp_impl(layer, x, y, button, shift);
	}
	protected virtual void OnMouseUp_impl(UTVPLayer layer, int x, int y, KeyCode button, int shift)
	{
		if (!mMouseDown)
			return;
		mouseDown = false;
	}
	
	private void MouseEnterHandler(UTVPLayer layer)
	{
		if (!disable)
			OnMouseEnter_impl(layer);
	}
	protected virtual void OnMouseEnter_impl(UTVPLayer layer)
	{
		if (mFocus)
			return;
		focus = true;
		
		if (enterSE != null)
			mSystem.SystemSeBuf.play(enterSE);
		else if (mSystem.DefaultCtlEnterSE != null)
			mSystem.SystemSeBuf.play(mSystem.DefaultCtlEnterSE);
	}
	
	private void MouseLeaveHandler(UTVPLayer layer)
	{
		if (!disable)
			OnMouseLeave_impl(layer);
	}
	protected virtual void OnMouseLeave_impl(UTVPLayer layer)
	{
		if (!mFocus)
			return;
		focus = false;
		
		if (leaveSE != null)
			mSystem.SystemSeBuf.play(leaveSE);
		else if (mSystem.DefaultCtlLeaveSE != null)
			mSystem.SystemSeBuf.play(mSystem.DefaultCtlLeaveSE);
	}
	
	public int CompareTo(UKagControlBase other)
	{
		if (this.tabIdx != other.tabIdx)
			return this.tabIdx - other.tabIdx;
		else
			return this.layer.AbsoluteIndex - other.layer.AbsoluteIndex;
	}
  
	protected virtual UKagControlBase_SaveData CreateSaveDataBuff()
	{
		return new UKagControlBase_SaveData();
	}
	
	protected virtual void GetSelfData(UKagControlBase_SaveData dataBuff)
	{
		dataBuff.stateAnimNamePrefix = stateAnimNamePrefix;
		dataBuff.isAnim = mIsAnim;
		dataBuff.tabIdx = tabIdx;
			
		dataBuff.focus = mFocus;
		dataBuff.disable = mDisable;
		dataBuff.mouseDown = mMouseDown;
		
		dataBuff.enterSE = enterSE.name;
		dataBuff.leaveSE = leaveSE.name;
		dataBuff.clickSE = clickSE.name;
	}

	public UKagControlBase_SaveData GetData()
	{
		UKagControlBase_SaveData dataBuff = CreateSaveDataBuff();
		GetSelfData(dataBuff);
		
		return dataBuff;
	}
	
	protected virtual void SetSelfData(UKagControlBase_SaveData dataBuff)
	{
		stateAnimNamePrefix = dataBuff.stateAnimNamePrefix;
		mIsAnim = dataBuff.isAnim;
		tabIdx = dataBuff.tabIdx;
			
		mFocus = dataBuff.focus;
		mDisable = dataBuff.disable;
		mMouseDown = dataBuff.mouseDown;
		
		UTVPAudio audioTemp = mStorages.GetAudio(dataBuff.enterSE);
		enterSE = audioTemp != null ? audioTemp.Clip : null;
		
		audioTemp = mStorages.GetAudio(dataBuff.leaveSE);
		leaveSE = audioTemp != null ? audioTemp.Clip : null;

		audioTemp = mStorages.GetAudio(dataBuff.clickSE);
		clickSE = audioTemp != null ? audioTemp.Clip : null;
	}
	
	public void SetData(UKagControlBase_SaveData dataBuff)
	{
		SetSelfData(dataBuff);
		
		RefreshControlState();
	}

}
